package org.xtetris;

import java.io.IOException;
import java.io.InputStream;

import javax.microedition.lcdui.Font;
import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;
import javax.microedition.midlet.MIDlet;

import org.util.Util;

public class Engine extends Device implements Runnable , MenuListener {
	private MIDlet midlet;
	private Thread t;
	public final static int FRAME_DURATION = 80;

	private long startTime , endTime;
	
	Image buffer;
	Graphics bg;
	
	private boolean debug;
	
	String info = "";
	
	private final static int TICKS_OF_SPLASH = 20;
	private int counter;
	
	Game game;
	
	final static int STATE_UNINITIALIZED = -1;
	final static int STATE_INITIALIZING = 0;
	final static int STATE_SPLASH = 1;
	final static int STATE_MAIN_MENU = 2;
	final static int STATE_GAME = 3;
	
	int state = STATE_UNINITIALIZED;
	int nextState;
	
	Image meImage;
	Image titleImage;
	
	Menu menu;
	
	
	public Engine(MIDlet midlet) {
		this.midlet = midlet;

		setFullScreenMode(true);

		fullScreenWidth = getWidth();
		fullScreenHeight = getHeight();
		
		halfFullScreenWidth = fullScreenWidth >> 1;
		halfFullScreenHeight = fullScreenHeight >> 1;
		
		buffer = Image.createImage(fullScreenWidth , fullScreenHeight);
		bg = buffer.getGraphics();
		
		t = new Thread(this);
		t.start();
		
		doRepaint();
	}

	public void run() {
		while (t != null) {
			long startTime = System.currentTimeMillis();

			tick();
			
			doRepaint();

			long duration = System.currentTimeMillis() - startTime;
			
//			if(duration == 0){
//				info = "-";
//			}else{
//				String pfs = "" + 100000 / (int)duration;
//				info = pfs.substring(0 , pfs.length() - 2) + "." + pfs.substring(pfs.length() - 2);			
//			}
			
			if (duration < FRAME_DURATION) {
				try {
					Thread.sleep(FRAME_DURATION - duration);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
		
		midlet.notifyDestroyed();
	}

	private void tick(){
		if(state == STATE_UNINITIALIZED){
//			try {
//				InputStream is = this.getClass().getResourceAsStream("/me.png");
//				meImage = Image.createImage(is);
//				
//				is = this.getClass().getResourceAsStream("/xtetris.png");
//				titleImage = Image.createImage(is);
//				
//				nextState = STATE_INITIALIZING;
//				setState();
//			} catch (IOException e) {
//				// TODO Auto-generated catch block
//				e.printStackTrace();
//			}
			nextState = STATE_INITIALIZING;
			setState();
		}else if(state == STATE_INITIALIZING){
			nextState = STATE_SPLASH;
			setState();
		}else if(state == STATE_GAME){
			game.tick();			
		}else if(state == STATE_SPLASH){
			if(counter ++ > TICKS_OF_SPLASH){
				nextState = STATE_MAIN_MENU;
				setState();
			}
		}else if(state == STATE_MAIN_MENU){
			menu.tick();
		}
	}
	
	private void setState(){
		if(state == STATE_UNINITIALIZED){
			if(nextState == STATE_INITIALIZING){
				state = STATE_INITIALIZING;
			}
		}else if(state == STATE_INITIALIZING){
			if(nextState == STATE_SPLASH){
				state = STATE_SPLASH;
			}
		}else if(state == STATE_SPLASH){
			if(nextState == STATE_GAME){
				game = new Game(this);
				state = STATE_GAME;
			}else if(nextState == STATE_MAIN_MENU){
				menu = new Menu(this , Menu.MENU_TYPE_MAIN_MENU , null , (fullScreenWidth - Menu.getWidth(Menu.MENU_TYPE_MAIN_MENU)) >> 1 , fullScreenHeight / 3 + ((fullScreenHeight) * 2 / 3 - Menu.getHeight(Menu.MENU_TYPE_MAIN_MENU)) >> 1 , this);
				state = STATE_MAIN_MENU;
			}
		}else if(state == STATE_MAIN_MENU){
			if(nextState == STATE_GAME){
				game = new Game(this);
				state = STATE_GAME;
			}
		}
	}
	
	private void doRepaint() {
		repaint();
		serviceRepaints();
	}
	
	protected void paint(Graphics g) {
		super.paint(g);

		if(state == STATE_UNINITIALIZED){
			bg.setColor(COLOR_BLACK);
			Util.fillRect(g, 0, 0, fullScreenWidth, fullScreenHeight);
			
			Font font = bg.getFont();
			int y = (fullScreenHeight - font.getHeight()) >> 1;
			
			bg.setColor(COLOR_WHITE);
			Util.drawString(bg ,"...", halfFullScreenWidth, y, Graphics.HCENTER | Graphics.TOP);
		}else if(state == STATE_INITIALIZING){
			bg.setColor(COLOR_BLACK);
			Util.fillRect(g, 0, 0, fullScreenWidth, fullScreenHeight);
		}else if(state == STATE_SPLASH){
			final Font font = bg.getFont();
			int y = fullScreenHeight / 3;
			
			bg.setColor(COLOR_BLACK);
			
			bg.setFont(FONT_TITLE);
			Util.drawString(bg, TEXT_XTETRIS_TITLE , halfFullScreenWidth, fullScreenHeight / 3, Graphics.HCENTER | Graphics.TOP);
			
			y += FONT_TITLE.getHeight();
			
			bg.setFont(FONT_ME);
			Util.drawString(bg, TEXT_ME, halfFullScreenWidth, y, Graphics.HCENTER | Graphics.TOP);
			
			y += FONT_ME.getHeight();
			
			bg.setFont(FONT_EMAIL);
			Util.drawString(bg, TEXT_EMAIL, halfFullScreenWidth, y, Graphics.HCENTER | Graphics.TOP);
		}else if(state == STATE_GAME){
			game.paint(bg);			
		}else if(state == STATE_MAIN_MENU){
			menu.paint(bg);
		}
		
		debug(bg);
		
		//now we are done rendering the buffer draw it to the screen
		g.drawImage(buffer , 0 , 0 , Graphics.LEFT | Graphics.TOP);
	}
	
	private void debug(Graphics g){
		if(debug){
			g.setColor(COLOR_BLACK);
			Util.drawString(g, info, fullScreenWidth, fullScreenHeight, Graphics.RIGHT | Graphics.BOTTOM);			
		}
	}

	public void itemSelected(Menu menu, int index) {
		// TODO Auto-generated method stub
		if(menu.id == Menu.MENU_TYPE_MAIN_MENU){
			if(index == 0){
				nextState = STATE_GAME;
				setState();
			}
		}
	}
}
